<template>
  <div class="filter-number-range">
    <div class="header">
      <span
        v-for="tab in tabData"
        :key="tab.key"
        :class="{ tabs: true, active: activeKey === tab.key }"
        @click="toggleTabKey(tab)"
      >
        {{ tab.name }}
      </span>
    </div>
    <div class="content">
      <a-radio-group v-model="filterPercentage" @change="toggleFilterType">
        <a-radio class="filter-type-radio" :value="false">
          值范围
        </a-radio>
        <a-radio class="filter-type-radio" :value="true">
          百分比
        </a-radio> </a-radio-group
      ><br />
      <span v-if="!filterPercentage">{{ tips }}</span>
      <div class="input">
        <a-input-number
          class="input-min"
          :disabled="activeKey === '<='"
          :value="inputMinValue"
          size="small"
          @change="onInputValue($event, 'min')"
        />
        <span v-if="filterPercentage">%</span>
        <a-input-number
          class="input-max"
          :disabled="activeKey === '>='"
          :value="inputMaxValue"
          size="small"
          @change="onInputValue($event, 'max')"
        />
        <span v-if="filterPercentage">%</span>
      </div>
      <vue-slider
        v-if="value.length === 1"
        ref="slider"
        v-model="value[0]"
        class="slider"
        :min="min"
        :max="max"
        tooltip="none"
        :direction="sliderDirection"
        :interval="interval"
        :silent="true"
        @change="onSliderChange"
        @drag-start="onSliderDragStart"
        @drag-end="emitFilterParams"
      />
      <vue-slider
        v-if="value.length === 2"
        ref="slider"
        v-model="value"
        class="slider"
        :min="min"
        :max="max"
        tooltip="none"
        :direction="sliderDirection"
        :interval="interval"
        :silent="true"
        @change="onSliderChange"
        @drag-start="onSliderDragStart"
        @drag-end="emitFilterParams"
      />
      <div v-if="filterPercentage" class="slider-value">
        <span>{{ percentageMin }}</span>
        <span>{{ percentageMax }}</span>
      </div>
      <a-checkbox :checked="nullChecked" @change="toggleNullChecked($event)"
        >包含null值</a-checkbox
      >
    </div>
  </div>
</template>

<script lang="ts">
import { Vue, Component, Prop, Watch } from 'vue-property-decorator'
import { IColumn, IKeyValueStore } from '@/store/modules/dataview'
import { ColumnStat } from '@/components/studio/data/node-edit-panel/interface'
import { StatisticsAction } from '@/util/data-selection-actions'
// @ts-ignore
import Big from 'big.js'
import VueSlider from 'vue-slider-component'
import 'vue-slider-component/theme/default.css'
import { apiGetPercentageValue, apiGetColumnStat } from '@/api/data-clean'

const filterTypeMapping = {
  between: '[a,b]',
  greater: '>=',
  lighter: '<=',
  per_between: 'a%-b%',
  per_lighter: '0%-b%',
  per_greater: 'a%-100%',
}

@Component({
  components: {
    VueSlider,
  },
})
export default class FilterNumberRange extends Vue {
  @Prop() requestParams: any
  @Prop() column!: IColumn
  @Prop() columnStat!: ColumnStat
  @Prop() editData!: any
  @Prop({ default: false }) isEdit!: boolean
  @Prop({ default: '' }) parentTableName!: boolean
  @Prop() taskId!: string
  @Prop() projectId!: number
  @Prop() tableName!: string
  private activeKey: '[a,b]' | '<=' | '>=' = '[a,b]'
  private min: number = 0
  private max: number = 2
  private interval: number = 1
  private value: number[] = [0]
  private sliderDirection: 'ltr' | 'rtl' = 'ltr'
  private nullChecked: boolean = false
  private sliderDrag: boolean = false
  private filterPercentage: boolean = false
  private percentageMin: number = 0
  private percentageMax: number = 2
  private lastHistoryMinMax: { min?: number; max?: number } = {}

  private tabData: any = [
    {
      name: '范围', // 范围区间
      key: filterTypeMapping.between,
    },
    {
      name: '大于',
      key: filterTypeMapping.greater,
    },
    {
      name: '小于',
      key: filterTypeMapping.lighter,
    },
  ]
  private get tips(): string {
    let tips = ''
    switch (this.activeKey) {
      case filterTypeMapping.between:
        tips = '只包括此范围中的值'
        break
      case filterTypeMapping.greater:
        tips = '只包括>=最小值的值'
        break
      case filterTypeMapping.lighter:
        tips = '只包括<=最大值的值'
        break
      default:
        break
    }
    return tips
  }

  /**
   * 根据百分比获取值
   */
  private async getPercentageValue(isMax: boolean) {
    const response = await apiGetPercentageValue({
      data: {
        col: this.requestParams.name,
        percentage: isMax ? this.inputMaxValue : this.inputMinValue,
        projectId: this.projectId,
        table: this.isEdit ? this.parentTableName : this.tableName,
        taskId: this.taskId,
        includeNull: this.nullChecked,
      },
    })
    if (response.data.code === 100) {
      if (isMax) {
        this.percentageMax = response.data.result.value
      } else {
        this.percentageMin = response.data.result.value
      }
    } else {
      this.$message.error(response.data.message)
    }
  }

  private onSliderChange() {
    if (this.sliderDrag) {
      // 拖拽中改变的值抛弃
      return
    }
    this.emitFilterParams()
  }

  private onSliderDragStart() {
    this.sliderDrag = true
  }

  private get inputMinValue() {
    let value = 0
    if (this.activeKey === filterTypeMapping.between) {
      ;[value] = this.value
    } else if (this.activeKey === filterTypeMapping.lighter) {
      value = this.min
    } else {
      value = this.max - this.value[0] + this.min
    }
    return value
  }

  private get inputPercentageMinValue() {
    const value = `${this.inputMinValue}%`
    if (this.filterPercentage) {
      return value
      // eslint-disable-next-line
    } else {
      return this.inputMinValue
    }
  }

  private get inputMaxValue() {
    let value = 0
    if (this.activeKey === filterTypeMapping.between) {
      ;[, value] = this.value as number[]
    } else if (this.activeKey === filterTypeMapping.greater) {
      value = this.max
    } else {
      // eslint-disable-next-line
      value = this.value[0]
    }
    return value
  }

  private get inputPercentageMaxValue() {
    if (this.filterPercentage) {
      return `${this.inputMaxValue}%`
      // eslint-disable-next-line
    } else {
      return this.inputMaxValue
    }
  }

  /**
   * 格式化抛出去的参数值
   */
  private get formatParamsValue() {
    let value = []
    if (this.activeKey === filterTypeMapping.between) {
      value = [`${this.inputMinValue}`, `${this.inputMaxValue}`]
    } else if (this.activeKey === filterTypeMapping.greater) {
      value = [`${this.inputMinValue}`]
    } else {
      value = [`${this.inputMaxValue}`]
    }
    return value
  }

  /**
   * 格式化抛出去的参数值
   */
  private get formatFilterType() {
    if (this.filterPercentage) {
      if (this.activeKey === '[a,b]') {
        return filterTypeMapping.per_between
        // eslint-disable-next-line
      } else if (this.activeKey === '<=') {
        return filterTypeMapping.per_lighter
        // eslint-disable-next-line
      } else {
        return filterTypeMapping.per_greater
      }
    }
    // eslint-disable-next-line
    else {
      return this.activeKey
    }
  }

  /**
   * 格式化抛出去的描述
   */
  private get formatDescription() {
    let description = ''
    if (this.activeKey === filterTypeMapping.greater) {
      description = `值≥${this.inputPercentageMinValue}`
    } else if (this.activeKey === filterTypeMapping.lighter) {
      description = `值≤${this.inputPercentageMaxValue}`
    } else {
      description = `值范围：${this.inputPercentageMinValue}-${this.inputPercentageMaxValue}`
    }
    if (this.nullChecked) {
      // 包含null值
      description += '(包含null值)'
    }
    return description
  }

  @Watch('columnStat', { immediate: true, deep: true })
  private onColumnStatChange(newValue: ColumnStat) {
    if (!newValue) {
      return
    }
    this.lastHistoryMinMax = {}
    if (!this.isEdit) {
      if (this.filterPercentage) {
        this.min = +0
        this.max = +100
        this.interval = 1
      } else {
        this.min = +newValue.min
        this.max = +newValue.max
        const bMax = new Big(this.max)
        if (this.column.desc === 'decimal') {
          // 小数的时候按50进行划分，整数间隔是1
          this.interval = +bMax.minus(this.min).div(50).toPrecision()
        }
      }
      this.percentageMin = +newValue.min
      this.percentageMax = +newValue.max
      this.setSliderValue()
    }
  }

  @Watch('editData', { immediate: true, deep: true })
  private onCurrentHistoryChange(newValue: IKeyValueStore) {
    if (!newValue || !this.isEdit) {
      return
    }
    const history = newValue.data
    if (
      history.actionType === StatisticsAction.filterNumberRange &&
      history.col === this.column.name
    ) {
      const data = history.filter[0][0]
      this.value = data.values.map((item: string) => +item)
      if (['a%-b%', 'a%-100%', '0%-b%'].includes(data.filterType)) {
        this.filterPercentage = true
        if (data.filterType === 'a%-b%') {
          this.activeKey = '[a,b]'
        } else if (data.filterType === 'a%-100%') {
          this.activeKey = '>='
        } else {
          this.activeKey = '<='
        }
      } else {
        this.activeKey = data.filterType
      }
      if (
        history.filter[0].length > 1 &&
        history.filter[0][1].values[0] === '#NULL'
      ) {
        // 包含null值
        this.nullChecked = true
      }
      this.getLastHistoryColumnData()
    }
  }

  /**
   * 编辑模式下需要根据上一个记录的表名来查询数据
   */
  async getLastHistoryColumnData() {
    /* eslint-disable unicorn/prevent-abbreviations */
    const requestParams = this.requestParams || {}
    if (this.isEdit) {
      // 编辑模式下，获取的选项是基于上一个记录的表进行查询
      requestParams.table = this.parentTableName // 编辑状态下是基于上一条记录的表名来进行筛选
    }
    const response = await apiGetColumnStat({
      data: {
        ...requestParams,
      },
    })
    if (!response.data.success) {
      return
    }
    const { result } = response.data
    this.lastHistoryMinMax = {
      min: result.min,
      max: result.max,
    }
    if (this.filterPercentage) {
      this.min = 0
      this.max = 100
      this.interval = 1
      this.getPercentageValue(true)
      this.getPercentageValue(false)
    } else {
      this.min = result.min
      this.max = result.max
    }
    if (this.column.desc === 'decimal') {
      // 小数的时候按50进行划分，整数间隔是1
      const bMax = new Big(this.max)
      this.interval = +bMax.minus(this.min).div(50).toPrecision()
    }
    if (this.activeKey === filterTypeMapping.greater) {
      this.sliderDirection = 'rtl'
      this.value = [this.max - this.value[0] + this.min]
    }
  }

  /**
   * 初始时根据min/max设置slider的值
   */
  setSliderValue() {
    this.sliderDirection = 'ltr'
    if (this.activeKey === filterTypeMapping.between) {
      this.value = [this.min, this.max]
    } else if (this.activeKey === filterTypeMapping.greater) {
      this.value = [this.max]
      this.sliderDirection = 'rtl'
    } else {
      this.value = [this.max]
    }
  }

  toggleTabKey(tab: any) {
    this.activeKey = tab.key
    this.setSliderValue()
    this.emitFilterParams()
  }

  toggleFilterType() {
    if (this.filterPercentage) {
      this.min = +0
      this.max = +100
      this.interval = 1
      this.setSliderValue()
    } else {
      this.min =
        this.isEdit && this.lastHistoryMinMax.min
          ? this.lastHistoryMinMax.min
          : +this.columnStat.min
      this.max =
        this.isEdit && this.lastHistoryMinMax.max
          ? this.lastHistoryMinMax.max
          : +this.columnStat.max
      const bMax = new Big(this.max)
      if (this.column.desc === 'decimal') {
        // 小数的时候按50进行划分，整数间隔是1
        this.interval = +bMax.minus(this.min).div(50).toPrecision()
      }
      this.setSliderValue()
    }
    this.emitFilterParams()
  }

  /**
   * 是否包含null值
   */
  toggleNullChecked(event: any) {
    const { checked } = event.target
    this.nullChecked = checked
    this.emitFilterParams()
  }

  /**
   * 抛出去filter参数
   */
  emitFilterParams() {
    this.sliderDrag = false
    if (this.filterPercentage) {
      this.getPercentageValue(true)
      this.getPercentageValue(false)
    }
    const filter: any = [
      // 抛出最终用于筛选的选项值
      [
        {
          col: this.column.name,
          filterType: this.formatFilterType,
          values: this.formatParamsValue,
        },
      ],
    ]
    if (this.nullChecked) {
      // 包含null值
      filter[0].push({
        col: this.column.name,
        filterType: '=',
        values: ['#NULL'],
      })
    }
    this.$emit('on-filter-params-change', {
      data: {
        action: 'FILTER',
        col: this.column.name,
        filter,
        description: this.formatDescription,
        actionType: StatisticsAction.filterNumberRange,
      },
    })
  }

  /**
   * 输入框失焦，这是slider值
   */
  // eslint-disable-next-line consistent-return
  private onInputValue(value: any, type: 'min' | 'max') {
    // console.log(event.target.value, type)
    // const value = +event.target.value
    // if (value < this.min || value > this.max) {
    //   return
    // }

    value = +value
    if (
      (type === 'max' && value < this.inputMinValue) ||
      (type === 'min' && value > this.inputMaxValue) ||
      Number.isNaN(value)
    ) {
      // eslint-disable-next-line consistent-return
      return
    }
    if (value < this.min) {
      value = this.min
    }
    if (value > this.max) {
      value = this.max
    }
    if (this.activeKey === filterTypeMapping.between) {
      this.$set(this.value as number[], type === 'min' ? 0 : 1, +value)
    } else if (this.activeKey === filterTypeMapping.greater) {
      this.value = [this.max - value + this.min]
    } else {
      this.value = [+value]
    }
    this.emitFilterParams()
  }
}
</script>

<style lang="less" scoped>
.filter-number-range {
  .header {
    align-items: center;
    background-color: #fff;
    border-bottom: 1px solid rgba(233, 233, 233, 0.8);
    color: #373b52;
    display: flex;
    font-size: 14px;
    height: 25px;
    justify-content: space-between;
    line-height: 26px;
    width: 100%;

    .tabs {
      cursor: pointer;
      display: inline-block;
      height: 25px;
      margin-right: 8px;
      padding: 0 12px;

      &.active {
        border-bottom: 2px solid #5963e5;
        color: #5963e5;
        font-weight: 500;
      }
    }
  }

  .content {
    margin-top: 14px;

    .filter-type-radio {
      color: #5d637e;
      font-size: 14px;
      font-weight: 400;
      height: 16px;
      line-height: 16px;
      margin-bottom: 10px;
    }

    .input {
      align-items: flex-end;
      display: flex;
      justify-content: space-between;

      .input-min,
      .input-max {
        margin-top: 8px;
        width: 40%;
      }
    }

    .slider {
      margin: 12px 5px;
    }

    .slider-value {
      color: #969696;
      display: flex;
      font-size: 12px;
      justify-content: space-between;
      margin-bottom: 10px;
      margin-top: -10px;
    }

    /deep/ .vue-slider-process {
      background-color: #5963e5;
    }

    /deep/ .vue-slider-dot-handle-focus {
      box-shadow: 0 0 1px 2px rgba(89, 99, 229, 0.36);
    }

    /deep/ .ant-input-number-handler-wrap {
      display: none;
    }
  }
}
</style>
